#include <SDL/SDL.h>
#include <assert.h>
#include <unistd.h>
#include <SDL/SDL_image.h>

//Time between two updates
#define UPDATE_TIME_MS 16
//Time between painting two screens
#define DISPLAY_TIME_MS 35

int quit = 0;

float pos = 0.0f;

void blit_tiles(SDL_Surface *img, SDL_Surface *scr, int x_tile_offset = 0, const int tiles_per_row = 16) {
  SDL_Rect src, dest;

  src.x = x_tile_offset;
  src.w = 16;
  src.h = 16;
  dest.w = 16;
  dest.h = 16;
  for(int ii = 0; ii < img->h; ii += 16) {
    int i = ii / 16;
    int x = i % tiles_per_row;
    int y = i / tiles_per_row;

    src.y = ii;
    dest.x = 800 - 320 + x * 19;
    dest.y = 400 - 300 + y * 18;
    SDL_BlitSurface(img, &src, scr, &dest);
  }
}

void update_world(float sec) {
  pos += 10 * sec;
  if(pos > 639) pos = 0;
}

int main(int argc, char **argv) {
  SDL_Surface *img, *scr;
  SDL_Event event;
  Uint32 last_ticks = 0;
  Uint32 last_display_ticks = 0;

  assert(SDL_Init(SDL_INIT_VIDEO) == 0);
  scr = SDL_SetVideoMode(640, 400, 8, SDL_HWSURFACE|SDL_ANYFORMAT|SDL_DOUBLEBUF);
  assert(scr);
  img = IMG_Load("hero2.tiles.png");
  assert(img);
  SDL_EventState(SDL_MOUSEMOTION, SDL_IGNORE); //Ignore all mouse movements...

  blit_tiles(img, scr);
  SDL_Flip(scr);
  last_ticks = SDL_GetTicks();
  while(!quit) {
    Uint32 ticks = SDL_GetTicks();
    Uint32 ms_past = ticks - last_ticks;

    if(ms_past >= UPDATE_TIME_MS) {
      float sec = ms_past / 1000.0f;
      //Update the world
      update_world(sec);
      printf("update: ticks = %lu ∆ = %lu\n", (unsigned long)ticks, (unsigned long)ms_past);
      while(SDL_PollEvent(&event) == 1 && quit == 0) {
	switch(event.type) {
	case SDL_QUIT:
	  quit = 2;
	  break;
	case SDL_MOUSEBUTTONDOWN:
	case SDL_MOUSEBUTTONUP:
	  printf("button=%d state=%d x=$%04hX y=$%04hX\n", event.button.button, event.button.state, event.button.x, event.button.y);
	  break;
	case SDL_KEYDOWN:
	case SDL_KEYUP:
	  printf("state=%d sym=$%04X\n", event.key.state, event.key.keysym.sym);
	  break;
	default:
	  printf("event.type = $%x\n", (unsigned int)event.type);
	}
      }
      last_ticks = ticks;
    }
    if(ticks - last_display_ticks >= DISPLAY_TIME_MS) {
      SDL_Rect rect = { pos, 350, 30, 30 };

      //Display the world
      printf("display: ticks = %lu ∆ = %lu\n", (unsigned long)ticks, (unsigned long)(ticks - last_display_ticks));
      last_display_ticks = ticks;
      SDL_FillRect(scr, NULL, SDL_MapRGB(scr->format, 0, 0, 0));
      SDL_FillRect(scr, &rect, SDL_MapRGB(scr->format, 0x11, 0x33, 0x6a));
      SDL_Flip(scr);
    }

    Uint32 now = SDL_GetTicks(); //At the end of the loop!
    Uint32 delta1 = last_ticks + UPDATE_TIME_MS - now;
    Uint32 delta2 = last_display_ticks + DISPLAY_TIME_MS - now;
    Uint32 new_delta = delta1 < delta2 ? delta1 : delta2;
    printf("now = %ld\n", (long)now);
    if(new_delta < 200) SDL_Delay(new_delta);
  }
  SDL_Quit();
  return 0;
}


// g++ square_display.cc -lSDL -lSDL_image -lpthread
